import fs from "node:fs"
import path from "node:path"

type RegistryItem = {
  name: string
  dependencies: string[] | undefined
  files: {
    name: string
    content: string
  }[]
  type: string
  componentPath: string
}

export const makeRegistry = () => {
  const outputBaseDir = "public/registry"
  const generatedFilePath = "__registry__/generated.ts"

  const sources = [
    { type: "ui", path: "src/components/ui" },
    { type: "demo", path: "src/components/docs" },
    { type: "pre-blocks", path: "src/app/pre-blocks" },
  ]

  const getAllFiles = (dirPath: string, arrayOfFiles: string[] = []): string[] => {
    if (!fs.existsSync(dirPath)) {
      console.warn(`Directory not found: ${dirPath}`)
      return []
    }
    const files = fs.readdirSync(dirPath)
    for (const file of files) {
      const fullPath = path.join(dirPath, file)
      if (fs.statSync(fullPath).isDirectory()) {
        getAllFiles(fullPath, arrayOfFiles)
      } else if ([".tsx", ".css", ".json", ".ts"].some((ext) => file.endsWith(ext))) {
        arrayOfFiles.push(fullPath)
      }
    }

    return arrayOfFiles
  }

  const registryEntries: string[] = []

  for (const { type, path: sourcePath } of sources) {
    const resolvedPath = path.resolve(sourcePath)

    if (!fs.existsSync(resolvedPath)) {
      console.warn(`Directory not found: ${resolvedPath}`)
      continue
    }

    const files = getAllFiles(resolvedPath)

    const filteredFiles =
      type === "demo" ? files.filter((file) => !file.includes("/anatomies/")) : files

    for (const filePath of filteredFiles) {
      const componentName = path.basename(filePath, ".tsx")
      const fileContent = fs.readFileSync(filePath, "utf-8")

      const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, "/")
      const relativeKey = path.relative(sourcePath, filePath).replace(/\\/g, "/")
      const key = `${type}/${relativeKey.replace(".tsx", "")}`

      const registryItem: RegistryItem = {
        name: componentName,
        dependencies: undefined,
        files: [
          {
            name: path.basename(filePath),
            content: fileContent,
          },
        ],
        type: `components:${type}`,
        componentPath: relativePath,
      }

      if (!["demo", "ui"].includes(type)) {
        const jsonOutputPath = path.join(outputBaseDir, `${key}.json`)
        const jsonDir = path.dirname(jsonOutputPath)
        if (!fs.existsSync(jsonDir)) {
          fs.mkdirSync(jsonDir, { recursive: true })
        }
        fs.writeFileSync(jsonOutputPath, JSON.stringify(registryItem, null, 2))
      }

      if (type !== "anatomies") {
        registryEntries.push(`
        "${key}": {
          name: "${componentName}",
          type: "registry:${type}",
          registryDependencies: undefined,
          files: ["${relativePath}"],
          component: React.lazy(() => import("@${relativePath.replace("src", "")}")),
          source: "",
          category: "undefined",
          subcategory: "undefined",
          chunks: []
        }
      `)
      }
    }
  }

  const generatedContent = `
// @ts-nocheck
// THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.
// It is generated by the build-registry script.

import React from "react";

const registry = {
  ${registryEntries.join(",\n")}
};

export default registry;
  `

  console.info("Generating registry files...")

  const loadingInterval = setInterval(() => {
    process.stdout.write(".")
  }, 500)

  const generatedDir = path.dirname(generatedFilePath)
  if (!fs.existsSync(generatedDir)) {
    fs.mkdirSync(generatedDir, { recursive: true })
  }
  fs.writeFileSync(generatedFilePath, generatedContent)

  clearInterval(loadingInterval)

  console.info("Registry generation complete.")
}
